package cn.uncode.baas.server.internal.module.data;

import com.mongodb.DB;
import com.mongodb.MongoException;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import cn.uncode.baas.server.database.DynamicMongoDB;
import cn.uncode.baas.server.exception.ValidateException;
import cn.uncode.baas.server.utils.DataUtils;
import org.jongo.Find;
import org.jongo.FindOne;
import org.jongo.Jongo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Service
public class DataNoSQLModule implements IDataModule {
	
	private static final Logger LOG = Logger.getLogger(DataNoSQLModule.class);
	
	@Autowired
	private DynamicMongoDB dynamicMongoDB;
	
	public List<Map<String, Object>> find(Object param){
		DataParamResolve dataParam = new DataParamResolve(DataUtils.convert2Map(param));
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		try {
			DB db = dynamicMongoDB.determineTargetMongoDB();
			Jongo jongo = new Jongo(db);
	        String sort = null, skip = null, limit = null;
	        if(dataParam.getParams().containsKey("sort")){
	        	sort = String.valueOf(dataParam.getParams().get("sort"));
	        	dataParam.getParams().remove("sort");
	        }else if(dataParam.getParams().containsKey("skip")){
	        	skip = String.valueOf(dataParam.getParams().get("skip"));
	        	dataParam.getParams().remove("skip");
	        }else if(dataParam.getParams().containsKey("limit")){
	        	limit = String.valueOf(dataParam.getParams().get("limit"));
	        	dataParam.getParams().remove("limit");
	        }
	        Find find = jongo.getCollection(dataParam.getTable()).find(dataParam.getMongoScript());
	        if(StringUtils.isNotBlank(sort)){
	        	find.sort(sort);
	        }
	        if(StringUtils.isNotBlank(skip)){
	        	find.skip(Integer.valueOf(skip));
	        }
	        if(StringUtils.isNotBlank(limit)){
	        	find.limit(Integer.valueOf(limit));
	        }
	        Iterator<Map> iterator = find.as(Map.class).iterator();  
	        while(iterator.hasNext()){
	            result.add(iterator.next());
	        }
		} catch (UnknownHostException e) {
			LOG.error("mongo find error", e);
		} catch (MongoException e) {
			LOG.error("mongo find error", e);
		}
        return result;
	}

	public Map<String, Object> findOne(Object param) {
		DataParamResolve dataParam = new DataParamResolve(DataUtils.convert2Map(param));
		Map<String, Object> result = null;
		try {
			DB db = dynamicMongoDB.determineTargetMongoDB();
	        Jongo jongo = new Jongo(db);
	        FindOne find = null;
	        if(StringUtils.isNotBlank(dataParam.getObjectId())){
	        	find = jongo.getCollection(dataParam.getTable()).findOne(dataParam.getObjectId());
	        }else{
	        	find = jongo.getCollection(dataParam.getTable()).findOne(dataParam.getMongoScript());
	        }
	        result = find.as(Map.class);
		} catch (UnknownHostException e) {
			LOG.error("mongo find error", e);
		} catch (MongoException e) {
			LOG.error("mongo find error", e);
		}
        return result;
	}

	public int update(Object param) {
		DataParamResolve dataParam = new DataParamResolve(DataUtils.convert2Map(param));
		try {
			DB db = dynamicMongoDB.determineTargetMongoDB();
	        Jongo jongo = new Jongo(db);
	        Map<String, Object> map = jongo.getCollection(dataParam.getTable()).findOne(dataParam.getObjectId()).as(Map.class);
	        Iterator<String> iter = dataParam.getParams().keySet().iterator();
	        while(iter.hasNext()){
	        	String key = iter.next();
	        	if(map.containsKey(key)){
	        		map.put(key, dataParam.getParams().get(key));
	        	}
	        }
	        jongo.getCollection(dataParam.getTable()).save(map);
		} catch (UnknownHostException e) {
			LOG.error("mongo find error", e);
		} catch (MongoException e) {
			LOG.error("mongo find error", e);
		}
        return 1;
	}

	public int remove(Object param) {
		DataParamResolve dataParam = new DataParamResolve(DataUtils.convert2Map(param));
		try {
			DB db = dynamicMongoDB.determineTargetMongoDB();
	        Jongo jongo = new Jongo(db);
	        if(StringUtils.isNotBlank(dataParam.getObjectId())){
	        	jongo.getCollection(dataParam.getTable()).remove(dataParam.getObjectId());
	        }else{
	        	jongo.getCollection(dataParam.getTable()).remove(dataParam.getMongoScript());
	        }
		} catch (UnknownHostException e) {
			LOG.error("mongo find error", e);
		} catch (MongoException e) {
			LOG.error("mongo find error", e);
		}
        return 1;
	}

	public Object insert(Object param) {
		DataParamResolve dataParam = new DataParamResolve(DataUtils.convert2Map(param));
		try {
			DB db = dynamicMongoDB.determineTargetMongoDB();
	        Jongo jongo = new Jongo(db);
	        jongo.getCollection(dataParam.getTable()).insert(dataParam.getParams());
		} catch (UnknownHostException e) {
			LOG.error("mongo find error", e);
		} catch (MongoException e) {
			LOG.error("mongo find error", e);
		}
        return 1;
	}

	@Override
	public int count(Object param) throws ValidateException {
		// TODO Auto-generated method stub
		return 0;
	}

	public void setDynamicMongoDB(DynamicMongoDB dynamicMongoDB) {
		this.dynamicMongoDB = dynamicMongoDB;
	}
	
	

}
